home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d8 / pdriver5.arc / TAIL.ASM < prev    next >
Assembly Source File  |  1989-12-17  |  13KB  |  530 lines

  1. ;   PC/FTP Packet Driver source, conforming to version 1.05 of the spec
  2. ;   Russell Nelson, Clarkson University.  July 20, 1988
  3. ;   Updated to version 1.08 Feb. 17, 1989.
  4. ;   Copyright 1988,1989 Russell Nelson
  5.  
  6. ;   This program is free software; you can redistribute it and/or modify
  7. ;   it under the terms of the GNU General Public License as published by
  8. ;   the Free Software Foundation, version 1.
  9. ;
  10. ;   This program is distributed in the hope that it will be useful,
  11. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ;   GNU General Public License for more details.
  14. ;
  15. ;   You should have received a copy of the GNU General Public License
  16. ;   along with this program; if not, write to the Free Software
  17. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.     include    defs.asm
  20.  
  21. code    segment byte public
  22.     assume    cs:code, ds:code
  23.  
  24.     extrn    phd_dioa: byte
  25.     extrn    phd_environ: word
  26.  
  27. ;usage_msg is of the form "usage: driver <packet_int_no> <args>"
  28.     extrn    usage_msg: byte
  29.  
  30. ;copyright_msg is of the form:
  31. ;"Packet driver for the foobar",CR,LF
  32. ;"Portions Copyright 19xx, J. Random Hacker".
  33.     extrn    copyright_msg: byte
  34.  
  35. copyleft_msg    label    byte
  36.  db "Packet driver skeleton copyright 1988-89, Russell Nelson.",CR,LF
  37.  db "This program is free software; see the file COPYING for details.",CR,LF
  38.  db "NO WARRANTY; see the file COPYING for details.",CR,LF
  39. crlf_msg    db    CR,LF,'$'
  40.  
  41. ;parse_args should parse the arguments.
  42. ;called with ds:si -> immediately after the packet_int_no.
  43.     extrn    parse_args: near
  44.  
  45.     extrn    our_isr: near, their_isr: dword
  46.     extrn    packet_int_no: byte
  47.     extrn    is_at: byte, sys_features: byte
  48.     extrn    int_no: byte
  49.     extrn    driver_class: byte
  50.  
  51. location_msg    db    "Packet driver loaded at segment ",'$'
  52.  
  53. packet_int_no_name    db    "Packet interrupt number ",'$'
  54. eaddr_msg    db    "My Ethernet address is ",'$'
  55.  
  56. signature    db    'PKT DRVR',0
  57. signature_len    equ    $-signature
  58.  
  59. already_msg    db    CR,LF,"There is already a packet driver at ",'$'
  60. packet_int_msg    db    CR,LF
  61.         db    "Error: <packet_int_no> should be in the range 0x60 to 0x80"
  62.         db    '$'
  63. int_msg        db    CR,LF
  64.         db    "Error: <int_no> should be no larger than "
  65. int_msg_num    label    word
  66.         db    "xx"
  67.         db    '$'
  68.  
  69. our_address    db    EADDR_LEN dup(?)
  70.     public    etopen_diagn
  71. etopen_diagn    db    0        ; errorlevel from etopen if set
  72.  
  73. ;etopen should initialize the device.  If it needs to give an error, it
  74. ;can issue the error message and quit to dos.
  75.     extrn    etopen: near
  76.  
  77. ;get the address of the interface.
  78. ;enter with es:di -> place to get the address, cx = size of address buffer.
  79. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  80.     extrn    get_address: near
  81.  
  82. already_error:
  83.     mov    dx,offset already_msg
  84.     mov    di,offset packet_int_no
  85.     call    print_number
  86.     mov    ax,4c05h        ; give errorlevel 5
  87.     int    21h
  88.  
  89. usage_error:
  90.     mov    dx,offset usage_msg
  91. error:
  92.     mov    ah,9
  93.     int    21h
  94.     mov    ax,4c0ah        ; give errorlevel 10
  95.     int    21h
  96.  
  97.     public    start_1
  98. start_1:
  99.     mov    dx,offset copyright_msg
  100.     mov    ah,9
  101.     int    21h
  102.  
  103.     mov    dx,offset copyleft_msg
  104.     mov    ah,9
  105.     int    21h
  106.  
  107.     mov    si,offset phd_dioa+1
  108.     cmp    byte ptr [si],CR    ;end of line?
  109.     je    usage_error
  110.  
  111. ;print the location we were loaded at.
  112.     mov    dx,offset location_msg
  113.     mov    ah,9
  114.     int    21h
  115.  
  116.     mov    ax,cs            ;print cs as a word.
  117.     call    wordout
  118.  
  119.     mov    dx,offset crlf_msg
  120.     mov    ah,9
  121.     int    21h
  122.  
  123.     mov    di,offset packet_int_no    ;parse the packet interrupt number
  124.     mov    bx,offset packet_int_no_name
  125.     call    get_number        ;  for them.
  126.  
  127.     call    parse_args
  128.  
  129.     cmp    byte ptr [si],CR    ;end of line?
  130.     jne    usage_error
  131.  
  132.     mov    dx,offset packet_int_msg;make sure that the packet interrupt
  133.     cmp    packet_int_no,60h    ;  number is in range.
  134.     jb    error
  135.     cmp    packet_int_no,80h
  136.     ja    error
  137.  
  138.     mov    ah,35h            ;get their packet interrupt.
  139.     mov    al,packet_int_no
  140.     int    21h
  141.  
  142.     lea    di,3[bx]        ;see if there is already a signature
  143.     mov    si,offset signature    ;  there.
  144.     mov    cx,signature_len
  145.     repe    cmpsb
  146.     je    already_error        ;yes, so we can't go there.
  147.  
  148.     mov    ah,0c0h
  149.     int    15h            ; es:bx <- sys features block
  150.     jc    old_bios
  151.     add    bx,5
  152.     mov    al,es:[bx]        ; get system feature byte
  153.     mov    sys_features,al
  154.     test    sys_features,40h    ; 2nd 8259?
  155.     jnz    two_8259s
  156. old_bios:
  157.     mov    ax,0f000h        ;ROM segment
  158.     mov    es,ax
  159.     mov    al,7            ;maximum interrupt on a PC
  160.     mov    int_msg_num,'7'+' '*256
  161.     cmp    word ptr es:[0fffeh],0fch    ;is this an AT?
  162.     jne    not_at            ;no.
  163. two_8259s:
  164.     mov    al,15            ;maximum interrupt on an AT
  165.     mov    int_msg_num,'1'+'5'*256
  166.  
  167.     inc    is_at            ;yes - remember that we've got an AT.
  168.     or    sys_features,40h    ; ATs have a 2nd 8259
  169.     cmp    int_no,2        ;map IRQ 2 to IRQ 9.
  170.     jne    not_at
  171.     mov    int_no,9
  172. not_at:
  173.  
  174.     mov    dx,offset int_msg    ;make sure that the packet interrupt
  175.     cmp    int_no,al        ;  number is in range.
  176.     jbe    int_ok
  177.     jmp    error
  178. int_ok:
  179.  
  180.     call    etopen            ;init the driver.  If any errors,
  181.                     ;this routine returns cy.
  182.     jc    no_resident
  183.  
  184.     push    dx            ;remember where they want to end.
  185.  
  186.     mov    ah,35h            ;remember their packet interrupt.
  187.     mov    al,packet_int_no
  188.     int    21h
  189.     mov    their_isr.offs,bx
  190.     mov    their_isr.segm,es
  191.  
  192.     mov    ah,25h            ;install our packet interrupt
  193.     mov    dx,offset our_isr
  194.     int    21h
  195.  
  196.     cmp    driver_class,1        ;Ethernet?
  197.     jne    print_addr_2        ;no, don't print what we don't have.
  198.  
  199.     push    ds
  200.     pop    es
  201.     mov    di,offset our_address
  202.     mov    cx,EADDR_LEN
  203.     call    get_address
  204.  
  205.     mov    dx,offset eaddr_msg
  206.     mov    ah,9
  207.     int    21h
  208.  
  209.     mov    cx,EADDR_LEN
  210.     mov    si,offset our_address
  211. print_addr:
  212.     push    cx
  213.     lodsb
  214.     mov    cl,' '            ;Don't eliminate leading zeroes.
  215.     call    byteout
  216.     pop    cx
  217.     cmp    cx,1
  218.     je    print_addr_1
  219.     mov    al,':'
  220.     call    chrout
  221. print_addr_1:
  222.     loop    print_addr
  223.  
  224.     mov    dx,offset crlf_msg    ;can't depend on DOS to newline for us.
  225.     mov    ah,9
  226.     int    21h
  227.  
  228. print_addr_2:
  229.  
  230.     mov    ah,49h            ;free our environment, because
  231.     mov    es,phd_environ        ;  we won't need it.
  232.     int    21h
  233.  
  234.     mov    bx,1            ;get the stdout handle.
  235.     mov    ah,3eh            ;close it in case they redirected it.
  236.     int    21h
  237.  
  238.     pop    dx            ;get their ending address.
  239.     add    dx,0fh            ;round up to next highest paragraph.
  240.     mov    cl,4
  241.     shr    dx,cl
  242.     mov    ah,31h            ;terminate, stay resident.
  243.     mov    al,etopen_diagn        ; errorlevel (0 - 9, just diagnostics)
  244.     int    21h
  245.  
  246. no_resident:
  247.     mov    ax,4c00h + 32        ; give errorlevel 32
  248.     cmp    al,etopen_diagn
  249.     ja    no_et_diagn        ; etopen gave specific reason?
  250.     mov    al,etopen_diagn        ; yes, use that for error level
  251. no_et_diagn:
  252.     int    21h
  253.  
  254. ;             Suggested errorlevels:
  255. ;
  256. ; _____________________  0 = normal
  257. ;              1 = unsuitable memory address given; corrected
  258. ; In most cases every-     2 = unsuitable IRQ level given; corrected
  259. ; thing should work as     3 = unsuitable DMA channel given; corrected
  260. ; expected for lev 1-5     4 = unsuitable IO addr given; corrected (only 1 card)
  261. ; _____________________     5 = packet driver for this int # already loaded
  262. ; External errors, when    20 = general cable failure (but pkt driver is loaded)
  263. ; corrected normal    21 = network cable is open             -"-
  264. ; operation starts    22 = network cable is shorted          -"-
  265. ; _____________________ 23 = 
  266. ; Packet driver not    30 = usage message
  267. ; loaded. A new load    31 = arguments out of range
  268. ; attempt must be done    32 = unspecified device initialization error
  269. ;            33 = 
  270. ;            34 = suggested memory already occupied
  271. ;            35 = suggested IRQ already occupied
  272. ;            36 = suggested DMA channel already occupied
  273. ;            37 = could not find the network card at this IO address
  274.  
  275.     public    get_number
  276. get_number:
  277.     mov    bp,10            ;we default to 10.
  278.     jmp    short get_number_0
  279.  
  280.     public    get_hex
  281. get_hex:
  282.     mov    bp,16
  283. ;get a hex number, skipping leading blanks.
  284. ;enter with si->string of digits,
  285. ;    bx -> dollar terminated name of number,
  286. ;    di -> dword to store the number in.  [di] is not modified if no
  287. ;        digits are given, so it acts as the default.
  288. ;return cy if there are no digits at all.
  289. ;return nc, bx:cx = number, and store bx:cx at [di].
  290. get_number_0:
  291.     push    bx            ;remember the name of this number.
  292.     call    skip_blanks
  293.     call    get_digit        ;is there really a number here?
  294.     jc    get_number_3
  295.     or    al,al            ;Does the number begin with zero?
  296.     jne    get_number_4        ;no.
  297.     mov    bp,8            ;yes - they want octal.
  298. get_number_4:
  299.  
  300.     xor    cx,cx            ;get a hex number.
  301.     xor    bx,bx
  302. get_number_1:
  303.     lodsb
  304.     cmp    al,'x'            ;did they really want hex?
  305.     je    get_number_5        ;yes.
  306.     cmp    al,'X'            ;did they really want hex?
  307.     je    get_number_5        ;yes.
  308.     call    get_digit        ;convert a character into an int.
  309.     jc    get_number_2        ;not a digit (neither hex nor dec).
  310.     xor    ah,ah
  311.     cmp    ax,bp            ;larger than our base?
  312.     jae    get_number_2        ;yes.
  313.  
  314.     push    ax            ;save the new digit.
  315.  
  316.     mov    ax,bp            ;multiply the low word by ten.
  317.     mul    cx
  318.     mov    cx,ax            ;keep the low word.
  319.     push    dx            ;save the high word for later.
  320.     mov    ax,bp
  321.     mul    bx
  322.     mov    bx,ax            ;we keep only the low word (which is our high word)
  323.     pop    dx
  324.     add    bx,ax            ;add the high result from earlier.
  325.  
  326.     pop    ax            ;get the new digit back.
  327.     add    cx,ax            ;add the new digit in.
  328.     adc    bx,0
  329.     jmp    get_number_1
  330. get_number_5:
  331.     mov    bp,16            ;change the base to hex.
  332.     jmp    get_number_1
  333. get_number_2:
  334.     dec    si
  335.     mov    [di],cx            ;store the parsed number.
  336.     mov    [di+2],bx
  337.     clc
  338.     jmp    short get_number_6
  339. get_number_3:
  340.     mov    cx,-1
  341.     mov    bx,-1
  342.     cmp    al,'?'            ;did they ask for the default?
  343.     je    get_number_2        ;yes - give them -1.
  344.     stc
  345. get_number_6:
  346.     pop    dx            ;get the name of the number back.
  347.  
  348.     pushf                ;save some stuff.
  349.     push    bx
  350.     push    cx
  351.     push    si
  352.     push    di
  353.     call    print_number
  354.     pop    di
  355.     pop    si
  356.     pop    cx
  357.     pop    bx
  358.     popf
  359.     ret
  360.  
  361.  
  362. print_number:
  363. ;enter with dx -> dollar terminated name of number, di ->dword.
  364. ;exit with the number printed and the cursor advanced to the next line.
  365.     mov    ah,9            ;print the name of the number.
  366.     int    21h
  367.     mov    al,'0'
  368.     call    chrout
  369.     mov    al,'x'
  370.     call    chrout
  371.     mov    ax,[di]            ;print the number in hex.
  372.     mov    dx,[di+2]
  373.     call    hexout
  374.     mov    al,' '
  375.     call    chrout
  376.     mov    al,'('
  377.     call    chrout
  378.     mov    ax,[di]            ;print the number in decimal.
  379.     mov    dx,[di+2]
  380.     call    decout
  381.     mov    al,')'
  382.     call    chrout
  383.     mov    al,CR
  384.     call    chrout
  385.     mov    al,LF
  386.     call    chrout
  387.     ret
  388.  
  389.  
  390.     public    skip_blanks
  391. skip_blanks:
  392.     lodsb                ;skip blanks.
  393.     cmp    al,' '
  394.     je    skip_blanks
  395.     cmp    al,HT
  396.     je    skip_blanks
  397.     dec    si
  398.     ret
  399.  
  400.  
  401. get_digit:
  402. ;enter with al = character
  403. ;return nc, al=digit, or cy if not a digit.
  404.     cmp    al,'0'            ;decimal digit?
  405.     jb    get_digit_1        ;no.
  406.     cmp    al,'9'            ;. .?
  407.     ja    get_digit_2        ;no.
  408.     sub    al,'0'
  409.     clc
  410.     ret
  411. get_digit_2:
  412.     or    al,20h
  413.     cmp    al,'a'            ;hex digit?
  414.     jb    get_digit_1
  415.     cmp    al,'f'            ;hex digit?
  416.     ja    get_digit_1
  417.     sub    al,'a'-10
  418.     clc
  419.     ret
  420. get_digit_1:
  421.     stc
  422.     ret
  423.  
  424.  
  425.     public    hexout
  426. hexout:
  427.     mov    cl,'0'            ;prepare to eliminate leading zeroes.
  428.     xchg    ax,dx            ;just output 32 bits in hex.
  429.     call    wordout            ;output dx.
  430.     xchg    ax,dx
  431.     jmp    wordout            ;output ax.
  432.  
  433.  
  434.     public    decout
  435. decout:
  436.     mov    si,ax            ;get the number where we want it.
  437.     mov    di,dx
  438.     or    ax,dx            ;is the number zero?
  439.     jne    decout_nonzero
  440.     mov    al,'0'            ;yes - easier to just print it, then
  441.     jmp    chrout            ;  to eliminate all but the last zero.
  442. decout_nonzero:
  443.  
  444.     xor    ax,ax            ;start with all zeroes in al,bx,bp
  445.     mov    bx,ax
  446.     mov    bp,ax
  447.  
  448.     mov    cx,32            ;32 bits in two 16 bit registers.
  449. decout_1:
  450.     shl    si,1
  451.     rcl    di,1
  452.     xchg    bp,ax
  453.     call    addbit
  454.     xchg    bp,ax
  455.     xchg    bx,ax
  456.     call    addbit
  457.     xchg    bx,ax
  458.     adc    al,al
  459.     daa
  460.     loop    decout_1
  461.  
  462.     mov    cl,'0'            ;prepare to eliminate leading zeroes.
  463.     call    byteout            ;output the first two.
  464.     mov    ax,bx            ;output the next four
  465.     call    wordout            ;output the next four
  466.     mov    ax,bp
  467. wordout:
  468.     push    ax
  469.     mov    al,ah
  470.     call    byteout
  471.     pop    ax
  472. byteout:
  473.     mov    ah,al
  474.     shr    al,1
  475.     shr    al,1
  476.     shr    al,1
  477.     shr    al,1
  478.     call    digout
  479.     mov    al,ah
  480. digout:
  481.     and    al,0fh
  482.     add    al,90h    ;binary digit to ascii hex digit.
  483.     daa
  484.     adc    al,40h
  485.     daa
  486.     cmp    al,cl            ;leading zero?
  487.     je    return
  488.     mov    cl,-1            ;no more leading zeros.
  489. chrout:
  490.     push    ax            ;print the char in al.
  491.     xchg    al,dl
  492.     mov    ah,2
  493.     int    21h
  494.     xchg    al,dl
  495.     pop    ax
  496. return:
  497.     ret
  498.  
  499.  
  500. addbit:    adc    al,al
  501.     daa
  502.     xchg    al,ah
  503.     adc    al,al
  504.     daa
  505.     xchg    al,ah
  506.     ret
  507.  
  508.     public    memory_test
  509. memory_test:
  510. ;enter with ax = segment of memory to test, cx = number of bytes to test.
  511. ;exit with ne, bx->failing byte if the memory test failed.
  512.     push    ds
  513.     mov    ds,ax
  514.     mov    bx,-1
  515. memory_test_1:
  516.     inc    bx
  517.     mov    ah,ds:[bx]        ;get a copy of the location.
  518.     mov    al,ah            ;try to store the complement.
  519.     not    al
  520.     mov    ds:[bx],al
  521.     cmp    ds:[bx],al        ;did the store work?
  522.     mov    ds:[bx],ah        ;(in any case, restore the original)
  523.     loope    memory_test_1        ;keep going if the store worked.
  524.     pop    ds
  525.     ret
  526.  
  527. code    ends
  528.  
  529.     end
  530.